# coding=utf-8

from Exploit.BaseExploit import *
from Common import rules
from concurrent.futures import ThreadPoolExecutor


class DirScan(Exploit):
    def __init__(self, target, clear_task_list):
        super().__init__()
        self.target = target
        self.all_rules = []
        self.dirscanlist = []
        self.clear_task_list = clear_task_list  # 这里的数据是Alivescan扫描存活下来的数据
        self.headers = {
            'User-Agent': 'Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36',
            'Connection': 'Keep-Alive', 'Range': 'bytes=0-102400'}

    def format_url(self, url, path):
        # 这里判断结尾是否存在/符号 如果有进行清除 ，并且拼接rule.py的规则中的路径 再返回一个url
        if url.endswith('/'):
            url = url.strip('/')
        if not path.startswith('/'):
            path = '/' + path
        return url + path

    def init_rules(self):
        config_file_rules = rules.common_rules.get('config_file')  # config文件泄露
        shell_scripts_rules = rules.common_rules.get('shell_scripts')  # shell的的脚本泄露
        editor_rules = rules.common_rules.get('editor')  # editor
        spring_rules = rules.common_rules.get('spring')  # spring的敏感路径
        web_app_rules = rules.common_rules.get('web_app')  # web_app的探测，类似pma solr weblogic Jboss
        php_probe_rules = rules.common_rules.get('php_probe')  # php探针
        asp_probe_rules = rules.common_rules.get('asp_probe')  # asp探针
        login_rules = rules.common_rules.get('login')
        other_rules = rules.common_rules.get('other')
        web_inf_rules = rules.common_rules.get('WEB-INF')
        self.all_rules += config_file_rules
        self.all_rules += shell_scripts_rules
        self.all_rules += editor_rules
        self.all_rules += spring_rules
        self.all_rules += web_app_rules
        self.all_rules += other_rules
        self.all_rules += php_probe_rules
        self.all_rules += asp_probe_rules
        self.all_rules += login_rules
        self.all_rules += web_inf_rules

    # 比较返回值是否跟自己在rule.py中记录的一致
    def compare_rule(self, rule, response_status, response_html, response_content_type):
        rule_status = [200, 206, rule.get('status')]
        if rule.get('status') and (response_status not in rule_status):
            return
        if rule.get('tag') and (rule['tag'] not in response_html):
            return
        if rule.get('type_no') and (rule['type_no'] in response_content_type):
            return
        if rule.get('type') and (rule['type'] not in response_content_type):
            return
        # 如果有符合上规则的话 那么就返回一个True
        return True

    def write_file(self, web_lists, target, page):
        workbook = openpyxl.load_workbook(abs_path + str(target) + ".xlsx")
        worksheet = workbook.worksheets[page]
        index = 0
        while index < len(web_lists):
            web = list()
            web.append(web_lists[index]['path'])
            web.append(web_lists[index]['url'])
            web.append(web_lists[index]['status'])
            worksheet.append(web)
            index += 1
        workbook.save(abs_path + str(target) + ".xlsx")
        workbook.close()

    def exploit(self, url):
        temp_url = url
        for rule in self.all_rules:
            temp_url_2 = temp_url
            url = self.format_url(temp_url_2, rule['path'])
            # print("[敏感文件扫描] 当前正在请求的url为： ", url)
            try:
                r = requests.get(url, headers=self.headers, verify=False, timeout=3)
            except Exception as e:
                return e
            response_status = r.status_code
            response_html = r.text
            response_content_type = r.headers['Content-Type']
            for white_rule in rules.white_rules:
                if self.compare_rule(white_rule, response_status, response_html, response_content_type):
                    pass
            # 这里是没有匹配到rule中的规则，就continue 进行下一个的规则判断
            if not self.compare_rule(rule, response_status, response_html, response_content_type):
                continue
            result_dict = {
                'path': '敏感路径',
                'url': url,
                'status': response_status
            }

            self.dirscanlist.append(result_dict)

    def main(self):
        '''
        [
            {'url': 'https://42.247.33.26', 'title': '统 一身份认证平台', 'status': 200, 'frame': None},
            {'url': 'https://42.247.33.26', 'title': '统一身份认证平台', 'status': 200, 'frame': None},
            {'url': 'https://42.247.33.26', 'title': '统一身份认证平台', 'status': 200, 'frame': None},
            {'url': 'https://42.247.33.26', 'title': '统一身份认证平台', 'status': 200, 'frame': None}
        ]
        :return:
        '''
        logging.info("DirScan Start")
        self.init_rules()  # 合并所有的规则 然后进行对应的路径遍历 探测
        p = ThreadPoolExecutor(10)
        temp_urls = []
        for aaa in self.clear_task_list:
            flag = 0
            for i in temp_urls:
                if aaa['url'] == i:
                    flag += 1
            if flag == 0:
                temp_urls.append(aaa['url'])
                p.submit(self.exploit, aaa['url'])

        p.shutdown()
        print(self.dirscanlist)
        # 写文件
        self.write_file(self.dirscanlist, self.target, 9)


if __name__ == '__main__':
    print(1)


